<!--setup语法糖,不需要再写哪些固定的setup函数格式了-->
<script setup>
  // 引入ref函数
  import {ref, reactive, watch, watchEffect, onBeforeMount,onMounted,onBeforeUpdate,onUpdated} from 'vue'
  /*
  响应式数据：在数据变化时，vue框架会将变量最新的值更新到dom树中，页面数据就是实时最新的
  非响应式数据：在数据变化时，vue框架不会将变量最新的值更新到dom树中，页面数据就不是实时最新的

  vue2中，数据不做特殊处理，默认就是响应式的
  vue3中，数据要经过ref /reactive函数的处理才是响应式的
    ref,reactive函数是vue框架中给我们提供的方法，导入进来即可使用
  ref处理的响应数据，在操作时需要注意
    在script标签中，操作ref的响应式数据需要通过,value的形式操作
    在template标签中，操作ref的响应式数据，无需使用.value

  */
  let counter = ref(10) // 等价于{value:10}

  // 让counter自增的方法
  function counterIncr(){
    counter.value++
  }

  // 让counter自减的方法
  function counterDesc(){
    counter.value--
  }

  // 展示counter的值
  function showCounter(){
    alert(counter.value)
  }


  // 插值表达式 语法{{ 数据名字/函数/对象调用API }},其不依赖标签，但要放到指定位置有点困难
  let name = "zyh love gwc"
  let getMsg=()=>{
    return "hello vue3 message"
  }
  let age = 19
  let bee = "蜜 蜂"
  let carts = [
    {"name":"可乐",price:3,number:10},
    {"name":"薯片",price:6,number:8}
  ]
  // 定义一个获得购物车总金额的一个方法
  function compute(){
    let count = 0
    for(let index in carts){
      count += carts[index].price * carts[index].number
    }
    return count
  }

  /**
   * 文本渲染
   * v-*** vue的指令
   * 1、命令必须依赖标签，在开始标签中使用
   */
  // 支持字符串模板
  let haha = 'haha'
  let msg = `hello ${haha}`
  let fontMsg="<font color='red'>你好</font>"

  /**
   * 属性渲染命令
   * v-bind 将数据绑定到元素的属性上
   * v-bind:属性名="数据名"
   * 可以简写为   :属性名="数据名"
   */
  let data = {
    logo:"http://www.atguigu.com/images/index_new/logo.png",
    name:"尚硅谷",
    url:"http://www.atguigu.com"
  }

  /**
   * 事件渲染命令
   * v-on:事件名称="函数名()"
   * v-on:时间名可以简写 @事件名
   * 原生js的事件名是 on*** onclick ondbclick onblur onfocus
   * vue中的事件名去掉on    click   dbclick  blur  focus
   */
  function fun1(){
    alert("h1")
  }
  function fun2(){
    counter.value++
  }
  function fun3(event){
    let flag = confirm('确定要访问目标链接吗')
    if(!flag){
      // 原生js编码方式阻止组件的默认行为
      event.preventDefault()
    }
  }
  function fun4(){ 
    alert("超链接被点击了")
  }

  /**
   * 响应式数据
   * 让一个普通数据转换为响应式数据 两种方式
   * 1、ref函数 更适合单个变量
   *    在script标签中操作ref响应式数据要通过.value
   *    在template中操作ref响应式数据则无需.value
   * 2、reactive函数 更适合对象
   *    在script template 操作reactive响应式数据都直接使用对象名.属性名的方式即可
   */
  let number = ref(10)
  let person = reactive({
    name:"",
    age:10
  })
  function incrAge(){
    person.age++
  }
  function incr(){
    number++
  }

  /**
   * 条件渲染
   * v-if = "表达式/数据" 数据为true 则当前元素会渲染进入dom树
   * v-else 自动和前一个v-if做取反操作
   * 
   * v-show="" 数据为true时，元素则展示在页面上，否则不展示
   * 
   * v-show vs v-if
   * v-if: 数据为false时，元素则不再dom树中了
   * v-show: 数据为false时，元素仍在dom树中，通过display的css样式控制元素隐藏
   */
  let flag = ref(true)
  function changeFlag(){
    flag.value = !flag.value
  }

  /**
   * 列表渲染
   * 
   */
  let shopping = reactive([
    {
      'name':'可乐',
      'price':5,
      'number':2
    },
    {
      'name':'炸鸡',
      'price':20,
      'number':1
    },
    {
      'name':'薯条',
      'price':7,
      'number':2
    }
  ])
  function deleteShop(index){
    shopping.splice(index,1)
  }
  function computeShop(){
    let totalPrice = 0
    for(let index in shopping){
      totalPrice += shopping[index].price*shopping[index].number
    }
    return totalPrice
  }

  function deleteAll(){
    shopping.splice(0, shopping.length)
  }

  /**
   * 双向绑定
   * 单向绑定：v-bind 响应式数据发生变化时，更新dom树。但用户操作页面内容则不会同步到响应式数据中
   * 双向绑定：v-model 页面上的数据由于用户的操作造成了改变，也会同步修改对应的响应式数据
   *           双向绑定一般都用于表单标签，提取用户的输入数据
   *           v-model:value="数据" 双向 绑定
   *           v-model:value 一般都省略 :value
   */
  let user = reactive({
    username:"",
    userpwd:"",
    hobby:[],
    intro:"",
    hometown:""
  })
  function clearForm(){
    user.username="",
    user.userpwd="",
    user.hobby=[],
    user.intro="",
    user.hometown=""
  }

  /**
   * 数据监听器
   * 双向绑定可以满足大部分需求
   */
  let firstName = ref("李")
  let lastName = reactive({
    name:"小花"
  })
  let fullName = ref("")

  // watch函数监听一个ref的响应式数据
  // watch(firstName, (newValue, oldValue)=>{
  //   console.log(`${oldValue}变为${newValue}`)
  //   fullName = firstName.value+lastName.name
  // })
  // watch函数监听一个reactive响应式数据 专门监听reactive响应式数据中的一个属性
  // watch(()=>{return lastName.name},(newValue, oldValue)=>{
  //   console.log(`${oldValue}变为${newValue}`)
  //   fullName = firstName.value+lastName.name
  // })
  // watch函数监听一个reactive响应式数据, 监听响应式数据中的所有属性
  // watch(()=>{return lastName}, (newValue, oldValue)=>{
  //   // console.log(`${oldValue}变为${newValue}`)
  //   fullName = firstName.value+lastName.name
  // },{deep:true, immediate:true})  // {deep:true 深度监听对象中的每一个属性, immediate:true 加载页面时直接执行一次}

  // watchEffect 一个更为高效的监听办法
  watchEffect(()=>{
    // 想监听的数据必须要在函数里边使用到
    fullName.value = firstName.value+lastName.name
  })

  /**
   * 生命周期，钩子函数
   * mounted: 将vue中dom树加载带.html文件中
   * updated: 组件因为响应式状态变更而更新其DOM树之后调用
   */
  // 挂载之前
  onBeforeMount(()=>{
    console.log("---------------onBeforeMount------------------")
    let ele = document.getElementById("counter")
    console.log(ele)
  })
  // 挂载之后
  onMounted(()=>{
    console.log("---------------onMounted------------------")
    let ele = document.getElementById("counter")
    console.log(ele)
  })
  // 更新之前
  onBeforeUpdate(()=>{
    console.log("---------------onBeforeUpdate------------------")
    let ele = document.getElementById("counter")
    console.log(counter.value, ele.innerText)
  })
  // 更新之后
  onUpdated(()=>{
    console.log("---------------onUpdated------------------")
    let ele = document.getElementById("counter")
    console.log(counter.value, ele.innerText)
  })
</script>

<template>
  <div>
    <button @click="counterIncr()">+</button>
    <span v-text="counter"></span>
    <button @click="counterDesc()">-</button>
    <button @click="showCounter()">showCounter</button>
    <br>
<!-- 插值表达式 -->
  <div>
    <h1>{{ name }}</h1> <!--调用变量-->
     name = {{ name }} <br> <!--调用变量-->
     getMsg的返回值: {{ getMsg() }} <br> <!--调用函数-->
     年龄：{{ age }}，是否成年: {{ age>18? '是': '否' }} <br> <!--插值表达式中一些常见的运算符-->
     {{ bee.split(' ').reverse().join('') }} <br> <!--插值表达式中支持对象调用一些api-->
     {{ carts[0].price*carts[0].number+ carts[1].price*carts[1].number }} <br>
     {{ compute() }} <br>
  </div>
    
<!-- 文本属性渲染 -->
  <div>
    <h1 v-text="name"></h1>
    <h1 v-text="`你好 ${msg}`"></h1>
    <h1 v-text="age>18?'成年':'未成年'"></h1>
    <h1 v-text="getMsg()"></h1>
    <h1 v-text="fontMsg"></h1>
    <h1 v-html="fontMsg"></h1>
  </div>

<!--属性渲染命令-->
  <div>
    <a v-bind:href="data.url">
      <img :src="data.logo" :title="data.name">
    </a>
    <br>
  </div>

<!-- 事件渲染命令 -->
  <div> 
    <!--事件的绑定函数-->
    <button v-on:click="fun1()">hello</button>
    <button v-on:click="fun2()">+</button>
    {{ counter }}
    <!--内联事件处理器-->
    <button v-on:click="counter--">-</button>
    <!--事件的修饰符 .once事件只绑定一次 prevent修饰符阻止组件的默认行为-->
    <button v-on:click.once="counter++">+(只有效一次)</button>
    <br>
    <!--提交确认的时候，更推荐这种方式-->
    <a v-bind:href="data.url" v-on:click="fun3($event)">尚硅谷</a>
    <br>
    <!--暂时没发现prevent的作用-->
    <a v-bind:href="data.url" v-on:click.prevent="fun4()">尚硅谷</a>
    <br>
  </div>

<!-- 响应式数据的处理方式 -->
  <div> 
    <button @click="incrAge()">age+</button>
    {{ person.age }}
    <br>
    <button @click="number++">number+</button>
    {{ number }}
    <br>
  </div>

<!-- 条件渲染表达式 -->
  <div> 
    <h1 id="ha" v-if="flag">哈哈哈</h1>
    <h1 id="hb" v-else>哭哭哭</h1>
    <h1 id="hc" v-show="flag">笑笑笑</h1>
    <button @click="changeFlag()">条件转换</button>
    <br>
  </div>

<!-- 列表渲染 -->
  <div> 
    <h1>购物车商品如下</h1>
    <table border="1px">
      <thead>
        <tr>
          <th>序号</th>
          <th>名称</th>
          <th>单价</th>
          <th>数量</th>
          <th>总价</th>
          <th>操作</th>
        </tr>
      </thead>
      <tbody v-if="shopping.length>0">
        <tr v-for="(item, index) in shopping" v-bind:key="index">
          <td v-text="index+1"></td>
          <td v-text="item.name"></td>
          <td v-text="item.price"></td>
          <td v-text="item.number"></td>
          <td v-text="item.price*item.number"></td>
          <td>
            <button @click="deleteShop(index)">删除</button>
          </td>
        </tr>
      </tbody>
      <tbody v-else>
        <tr>
          <td colspan="6">
            购物车为空
          </td>
        </tr>
      </tbody>
    </table>
    <h1 v-text="`购物车总价为: ${computeShop()}`"></h1>
    <button @click="deleteAll()">
      <h5>一键清除购物车</h5>
    </button>
    <hr>
  </div>

<!-- 双向绑定 -->
  <div> 
    <h1>请注册用户信息</h1>
    <form>
      username:<input type="text" v-model="user.username"> <br>
      userpwd:<input type="password" v-model="user.userpwd"> <br>
      hobby: 唱 <input type="checkbox" name="hobbies" v-model="user.hobby" value="sing">
             跳 <input type="checkbox" name="hobbies" v-model="user.hobby" value="dance">
             rap <input type="checkbox" name="hobbies" v-model="user.hobby" value="rap"> <br>
      简介: <textarea v-model="user.intro"></textarea> <br>
      籍贯: <select v-model="user.hometown">
              <option value="1">河南</option>
              <option value="2">安徽</option>
              <option value="3">上海</option>
            </select> <br>
      一键清空: <button @click="clearForm()">清空信息</button>
    </form>
    {{ user }}
    <hr>
  </div>
<!-- 数据监听 -->
  <div> 
    firstName: <input type="text" v-model="firstName"> <br>
    lastName: <input type="text" v-model="lastName.name"> <br>
    fullName: {{ fullName }}
    <hr>
  </div>

<!-- 生命周期-钩子函数 -->
  <div> 
    <span id="counter">{{ counter }}</span>
    <button @click="counter++">counter++</button>
    <hr>
  </div>
  </div>
</template>

<style scoped>
</style>
